/*
 *    Copyright (c) 2018-2025, lengleng All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 * this list of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * Neither the name of the seckill4cloud.com developer nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * Author: lengleng (wangiegie@gmail.com)
 */
package com.jalonjia.seckill.core.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jalonjia.seckill.common.core.util.R;
import com.jalonjia.seckill.common.security.util.SecurityUtils;
import com.jalonjia.seckill.core.entity.SeckillActivity;
import com.jalonjia.seckill.core.entity.SeckillOrder;
import com.jalonjia.seckill.core.entity.SeckillOrderExcelVO;
import com.jalonjia.seckill.core.entity.SeckillTarget;
import com.jalonjia.seckill.core.mapper.SeckillOrderMapper;
import com.jalonjia.seckill.core.service.SeckillActivityService;
import com.jalonjia.seckill.core.service.SeckillOrderService;
import com.jalonjia.seckill.core.service.SeckillTargetService;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 秒杀订单表
 *
 * @author 贾晓超
 * @date 2022-05-05 20:56:44
 */
@Service
public class SeckillOrderServiceImpl extends ServiceImpl<SeckillOrderMapper, SeckillOrder> implements SeckillOrderService {
	private static final int ACTIVITY_TYPE_SEND = 1;
	@Autowired
	private SeckillTargetService seckillTargetService;
	@Autowired
	private SeckillActivityService seckillActivityService;
	@Autowired
	private SeckillOrderMapper seckillOrderMapper;

	@Override
	public void saveOrder(SeckillOrder seckillOrder) {
		if (seckillOrder == null) {
			return;
		}
		//验证秒杀活动时间
		SeckillActivity seckillActivity = seckillActivityService.getById(seckillOrder.getActivityNo());
		if (seckillActivity == null) {
			log.warn("秒杀活动不存在");
			return;
		}
		LocalDateTime now = LocalDateTime.now();
		if (now.isBefore(seckillActivity.getStartTime())) {
			log.warn("秒杀未开始提单");
			return;
		}
		if (now.isAfter(seckillActivity.getEndTime())) {
			log.warn("秒杀结束后提单");
			return;
		}
		if (haveOrderByActivityNo(seckillOrder.getActivityNo(), seckillOrder.getCreateBy())) {
			log.warn("重复提单");
			return;
		}
		//验证秒杀对象数量
		SeckillTarget seckillTarget = seckillTargetService.getById(seckillActivity.getTargetNo());
		if (seckillTargetService.reduceRemainNum(seckillTarget.getId())) {
			seckillOrder.setStatus(1);
		} else {
			log.error("Redis未拦截超卖订单");
		}
		// 活动类型为分发
		if (seckillActivity.getType() == ACTIVITY_TYPE_SEND) {
			seckillOrder.setFormValue(RandomUtil.randomString(10));
		}
		save(seckillOrder);
	}

	@Override
	public boolean haveOrderByActivityNo(Long activityNo, String username) {
		if (StrUtil.isEmpty(username)) {
			return true;
		}
		// 测试账号准许通过
		if (StrUtil.equals(username, "test")) {
			return false;
		}
		Long count = query()
				.eq("activity_no", activityNo)
				.eq("create_by", username)
				.count();
		return count > 0;
	}

	@Override
	public R getSeckillOrderPage(Page page, SeckillOrder seckillOrder) {
		return R.ok(page(page, getSeckillOrderWrapper(seckillOrder).orderByDesc("create_time")));
	}


	@Override
	public List<SeckillOrderExcelVO> export(SeckillOrder seckillOrder) {
		List<SeckillOrder> orderList = seckillOrderMapper.selectList(getSeckillOrderWrapper(seckillOrder));
		return orderList.stream().map(order -> {
			SeckillOrderExcelVO excelVO = new SeckillOrderExcelVO();
			BeanUtils.copyProperties(order, excelVO);
			return excelVO;
		}).collect(Collectors.toList());
	}


	private QueryWrapper<SeckillOrder> getSeckillOrderWrapper(SeckillOrder seckillOrder) {
		QueryWrapper<SeckillOrder> wrapper = new QueryWrapper<>();
		// 管理员可查询
		if (SecurityUtils.isAdmin()) {
			if (seckillOrder.getActivityNo() != null && !seckillOrder.getActivityNo().equals(0L)) {
				wrapper.eq("activity_no", seckillOrder.getActivityNo());
			}
			if (!StrUtil.isEmpty(seckillOrder.getCreateBy())) {
				wrapper.eq("create_by", seckillOrder.getCreateBy());
			}
		} else {
			// 非管理员
			wrapper.eq("create_by", SecurityUtils.username());
			List<Long> seckillActivityList = seckillActivityService.query()
					.eq("create_by", SecurityUtils.username())
					.list()
					.stream().map(SeckillActivity::getId)
					.collect(Collectors.toList());
			if (seckillActivityList.size() > 0) {
				wrapper.or().in("activity_no", seckillActivityList);
			}
		}
		return wrapper;
	}

}
